import numpy as np

# 生成数据集：两个类别，每个类别100个样本，使用高斯分布生成2D数据
np.random.seed(42)  # 设置随机种子以确保可重复性
class1 = np.random.normal(loc=[-2, -2], scale=1, size=(100, 2))  # 第一类：均值[-2, -2]，标准差1
class2 = np.random.normal(loc=[2, 2], scale=1, size=(100, 2))   # 第二类：均值[2, 2]，标准差1
X = np.vstack((class1, class2))  # 合并特征矩阵，形状(200, 2)
y = np.hstack((-np.ones(100), np.ones(100)))  # 标签：第一类-1，第二类+1

# 初始化参数：权重w和偏置b
w = np.zeros(X.shape[1])  # 权重向量，初始化为0，形状(2,)
b = 0.0  # 偏置，初始化为0
learning_rate = 0.01  # 学习率
epochs = 1000  # 训练轮数
C = 1.0  # 正则化参数，控制软间隔

# 训练SVM模型：使用梯度下降最小化hinge损失函数
for epoch in range(epochs):
    # 计算每个样本的预测值：y_pred = w * x + b
    y_pred = np.dot(X, w) + b
    # 计算hinge损失的子梯度：对于误分类样本，梯度为 -y*x + lambda*w，对于正确分类无贡献
    misclassified = y * y_pred < 1  # 找到违反间隔的样本（hinge损失>0）
    # 更新权重w：w = w - lr * (w - C * sum(y_i * x_i for misclassified))
    dw = w - C * np.dot(y[misclassified], X[misclassified]) / len(X)
    w -= learning_rate * dw
    # 更新偏置b：b = b - lr * (-C * sum(y_i for misclassified))
    db = -C * np.sum(y[misclassified]) / len(X)
    b -= learning_rate * db

# 定义预测函数：对新样本进行分类
def predict(x):
    return np.sign(np.dot(x, w) + b)  # 返回1或-1

# 测试模型：计算训练集准确率
predictions = predict(X)
accuracy = np.mean(predictions == y)
print(f"训练准确率: {accuracy * 100:.2f}%")

# 输出模型参数
print(f"权重w: {w}")
print(f"偏置b: {b}")